#include <iostream>
#include <string.h>

using namespace std;

class CowString
{
public:
    CowString()
    :_pstr(new char[5]()+4)
    {
        ++*(int *)(_pstr-4);
    }

    CowString(const char *pstr)
    :_pstr(new char[strlen(pstr)+5]()+4)
    {
        strcpy(_pstr,pstr);
        ++*(int *)(_pstr-4);
    }

    CowString(const CowString &rhs)
    :_pstr(rhs._pstr)
    {
        ++*(int *)(_pstr-4);
    }

    CowString &operator=(const CowString &rhs){
        if(this!=&rhs){
            if(--*(int *)(_pstr-4)==0){
                delete[] (_pstr-4);
            }
            _pstr=rhs._pstr;
            ++*(int *)(_pstr-4);
        }
        return *this;
    }

    ~CowString(){
        if(--*(int *)(_pstr-4)==0){
            delete[] (_pstr-4);
        }
    }

    int refcount() const{
        return *(int *)(_pstr-4);
    }

    int size() const{
        return strlen(_pstr);
    }

    const char *c_str() const{
        return _pstr;
    }

    char &operator[](int index){
        if(index>=size()){
            static char nullchar='\0';
            return nullchar;
        }
        if(*(int *)(_pstr-4)>1){
            char *temp=new char[strlen(_pstr)+5]()+4;
            strcpy(temp,_pstr);
            --*(int *)(_pstr-4);
            _pstr=temp;
            *(int *)(_pstr-4)=1;
        }
        return _pstr[index];
    }

    char &operator[](int index) const{
        if(index>=size()){
            static char nullchar='\0';
            return nullchar;
        }
        return _pstr[index];
    }

    friend ostream &operator<<(ostream &os,const CowString &rhs);

private:
    char *_pstr;
};

ostream &operator<<(ostream &os,const CowString &rhs){
    os<<rhs._pstr;
    return os;
}

void test(){
    CowString s1("hello");
    CowString s2=s1;
    CowString s3=s1;
    cout << s1.refcount() << ":" << s2.refcount() <<  endl;
    cout << s2[0] << endl;
    cout << s1.refcount() << ":" << s2.refcount() <<  endl;
}

int main()
{
    test();
    return 0;
}

